from machine import Pin, SoftI2C, Timer
from ssd1306 import SSD1306_I2C
import onewire, ds18x20, time
import network
import socket
import json

# 网络配置 - 请修改为你的WiFi信息
WIFI_SSID = "xishi"
WIFI_PASSWORD = "778166999"

# 系统配置
HISTORY_SIZE = 50  # 温度历史记录条数
API_VERSION = "v1"  # API版本

# 初始化相关模块
i2c = SoftI2C(sda=Pin(42), scl=Pin(40))
oled = SSD1306_I2C(128, 64, i2c, addr=0x3c)
WIFI_LED = Pin(46, Pin.OUT)  # WiFi连接状态指示灯

# 初始化 DS18B20
ow = onewire.OneWire(Pin(2))  # 使能单总线
ds = ds18x20.DS18X20(ow)     # 传感器是 DS18B20
rom = ds.scan()              # 扫描单总线上的传感器地址

# 确保找到了DS18B20传感器
if not rom:
    oled.fill(0)
    oled.text("No DS18B20 found!", 0, 20)
    oled.show()
    raise RuntimeError("未找到DS18B20传感器")

# 温度数据历史记录
temperature_history = []
current_temperature = 0

def temp_get(tim):
    global current_temperature, temperature_history
    try:
        ds.convert_temp()
        time.sleep_ms(750)  # 等待转换完成
        current_temperature = ds.read_temp(rom[0])
        
        # 添加到历史记录
        timestamp = time.time()
        temperature_history.append({"timestamp": timestamp, "temperature": current_temperature})
        
        # 保持历史记录在指定大小
        if len(temperature_history) > HISTORY_SIZE:
            temperature_history.pop(0)
            
        # OLED 数据显示
        oled.fill(0)
        oled.text('Temp Monitor', 0, 0)
        oled.text('Current: {:.2f} C'.format(current_temperature), 0, 20)
        
        # 显示WiFi连接状态
        sta_if = network.WLAN(network.STA_IF)
        if sta_if.isconnected():
            oled.text('WiFi: Connected', 0, 40)
        else:
            oled.text('WiFi: Disconnected', 0, 40)
            
        # 显示记录数量
        oled.text(f'Records: {len(temperature_history)}', 0, 55)
        oled.show()
        
    except Exception as e:
        oled.fill(0)
        oled.text('Temp Read Error', 0, 20)
        oled.text(str(e), 0, 40)
        oled.show()

# 连接WiFi
def connect_wifi():
    oled.fill(0)
    oled.text("Connecting WiFi...", 0, 20)
    oled.show()
    
    sta_if = network.WLAN(network.STA_IF)
    if not sta_if.isconnected():
        print('Connecting to network...')
        sta_if.active(True)
        sta_if.connect(WIFI_SSID, WIFI_PASSWORD)
        
        WIFI_LED.value(0)  # 开始连接时LED熄灭
        start_time = time.time()  # 记录开始时间
        
        # 连接过程中LED闪烁
        while not sta_if.isconnected():
            WIFI_LED.value(1)
            time.sleep_ms(300)
            WIFI_LED.value(0)
            time.sleep_ms(300)
            
            # 超时判断 (30秒)
            if time.time() - start_time > 30:
                print('WiFi连接超时!')
                oled.fill(0)
                oled.text('WiFi Timeout!', 0, 20)
                oled.show()
                return None
    
    if sta_if.isconnected():
        WIFI_LED.value(1)  # 连接成功LED常亮
        ip, subnet, gateway, dns = sta_if.ifconfig()
        
        # 打印网络信息到串口
        print('网络配置:')
        print(f'IP: {ip}')
        print(f'Subnet: {subnet}')
        print(f'Gateway: {gateway}')
        print(f'DNS: {dns}')
        
        # 显示网络信息到OLED
        oled.fill(0)
        oled.text('WiFi Connected!', 0, 0)
        oled.text(f'IP: {ip}', 0, 20)
        oled.text(f'GW: {gateway}', 0, 38)
        oled.text(f'SN: {subnet}', 0, 56)
        oled.show()
        
        time.sleep(2)  # 显示2秒后继续
        return ip
    else:
        WIFI_LED.value(0)  # 连接失败LED熄灭
        oled.fill(0)
        oled.text('WiFi Failed!', 0, 20)
        oled.show()
        return None

# 生成API文档页面
def generate_api_docs(ip):
    docs = f"""
    <html>
        <head>
            <title>温度监控API文档</title>
            <style>
                body {{ font-family: Arial; max-width: 800px; margin: 0 auto; padding: 20px; }}
                h1 {{ color: #333; }}
                .endpoint {{ background-color: #f5f5f5; padding: 15px; margin-bottom: 20px; border-radius: 5px; }}
                .method {{ display: inline-block; background-color: #4CAF50; color: white; padding: 5px 10px; border-radius: 3px; margin-right: 10px; }}
                .url {{ font-family: monospace; font-size: 16px; }}
                pre {{ background-color: #e9e9e9; padding: 10px; border-radius: 3px; overflow-x: auto; }}
            </style>
        </head>
        <body>
            <h1>温度监控API文档 - 版本 {API_VERSION}</h1>
            
            <div class="endpoint">
                <span class="method">GET</span>
                <span class="url">http://{ip}/</span>
                <p>简单的温度显示页面</p>
            </div>
            
            <div class="endpoint">
                <span class="method">GET</span>
                <span class="url">http://{ip}/api</span>
                <p>API根路径，返回可用API列表</p>
            </div>
            
            <div class="endpoint">
                <span class="method">GET</span>
                <span class="url">http://{ip}/api/{API_VERSION}/temperature</span>
                <p>获取当前温度</p>
                <pre>{{"temperature": 25.6, "unit": "C", "timestamp": 1620000000}}</pre>
            </div>
            
            <div class="endpoint">
                <span class="method">GET</span>
                <span class="url">http://{ip}/api/{API_VERSION}/history</span>
                <p>获取温度历史记录</p>
                <pre>[{{"timestamp": 1620000000, "temperature": 25.6}}, ...]</pre>
            </div>
            
            <div class="endpoint">
                <span class="method">GET</span>
                <span class="url">http://{ip}/api/{API_VERSION}/stats</span>
                <p>获取温度统计信息</p>
                <pre>{{
                    "min": 23.5,
                    "max": 27.8,
                    "avg": 25.6,
                    "count": 50,
                    "latest": 25.6
                }}</pre>
            </div>
            
            <div class="endpoint">
                <span class="method">GET</span>
                <span class="url">http://{ip}/api/{API_VERSION}/docs</span>
                <p>获取API文档</p>
            </div>
        </body>
    </html>
    """
    return docs

# 生成温度统计信息
def get_temperature_stats():
    if not temperature_history:
        return {
            "min": 0,
            "max": 0,
            "avg": 0,
            "count": 0,
            "latest": current_temperature
        }
    
    temps = [record["temperature"] for record in temperature_history]
    return {
        "min": min(temps),
        "max": max(temps),
        "avg": sum(temps) / len(temps),
        "count": len(temps),
        "latest": current_temperature
    }

# 启动Web服务器
def start_web_server():
    ip = connect_wifi()
    if not ip:
        oled.fill(0)
        oled.text('Web Server', 0, 10)
        oled.text('WiFi Failed!', 0, 30)
        oled.show()
        print('Web服务器启动失败：WiFi连接失败')
        return
    
    # 创建socket
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.bind(('0.0.0.0', 80))
    s.listen(5)
    
    oled.fill(0)
    oled.text('Web Server', 0, 10)
    oled.text('Listening on:', 0, 25)
    oled.text(ip, 0, 40)
    oled.show()
    
    print('Web服务器已启动，等待连接...')
    
    while True:
        conn, addr = s.accept()
        print('客户端连接来自:', addr)
        try:
            request = conn.recv(1024).decode('utf-8')
            if not request:
                conn.close()
                continue
                
            # 解析请求路径
            request_lines = request.split('\r\n')
            request_line = request_lines[0].split()
            if len(request_line) < 2:
                conn.close()
                continue
                
            method, path = request_line[0], request_line[1]
            
            # 处理API请求
            if path == '/':
                # 主页
                response = """HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n
                <html>
                    <head>
                        <title>温度监控</title>
                        <meta http-equiv="refresh" content="5">
                        <style>
                            body {{ font-family: Arial; text-align: center; padding-top: 30px; }}
                            .container {{ max-width: 600px; margin: 0 auto; }}
                            .temp-display {{ font-size: 64px; color: #333; margin: 30px 0; }}
                            .stats {{ background-color: #f5f5f5; padding: 20px; border-radius: 10px; }}
                            .api-link {{ margin-top: 20px; }}
                        </style>
                    </head>
                    <body>
                        <div class="container">
                            <h1>实时温度监控</h1>
                            <div class="temp-display">
                                {:.2f} &deg;C
                            </div>
                            <div class="stats">
                                <p>更新时间: {}</p>
                                <p>历史记录条数: {} 条</p>
                            </div>
                            <div class="api-link">
                                <a href="/api/docs">查看API文档</a>
                            </div>
                        </div>
                    </body>
                </html>""".format(current_temperature, time.ctime(), len(temperature_history))
            
            elif path.startswith('/api'):
                # API请求
                if path == '/api':
                    # API根路径
                    response = """HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n{
                        "version": "%s",
                        "endpoints": [
                            "/api/%s/temperature",
                            "/api/%s/history",
                            "/api/%s/stats",
                            "/api/%s/docs"
                        ]
                    }""" % (API_VERSION, API_VERSION, API_VERSION, API_VERSION, API_VERSION)
                
                elif path == f'/api/{API_VERSION}/temperature':
                    # 当前温度API
                    response = """HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n{
                        "temperature": %.2f,
                        "unit": "C",
                        "timestamp": %d
                    }""" % (current_temperature, time.time())
                
                elif path == f'/api/{API_VERSION}/history':
                    # 温度历史API
                    response = """HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n"""
                    response += json.dumps(temperature_history)
                
                elif path == f'/api/{API_VERSION}/stats':
                    # 温度统计API
                    response = """HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n"""
                    response += json.dumps(get_temperature_stats())
                
                elif path == f'/api/{API_VERSION}/docs':
                    # API文档
                    response = """HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"""
                    response += generate_api_docs(ip)
                
                else:
                    # API路径未找到
                    response = "HTTP/1.1 404 Not Found\r\nContent-Type: text/plain\r\n\r\nAPI endpoint not found"
            
            else:
                # 其他路径
                response = "HTTP/1.1 404 Not Found\r\nContent-Type: text/plain\r\n\r\nPage Not Found"
            
            conn.send(response.encode('utf-8'))
            conn.close()
        except Exception as e:
            print('处理请求时出错:', e)
            conn.close()

# 开启RTOS定时器，周期为2000ms
tim = Timer(-1)
tim.init(period=2000, mode=Timer.PERIODIC, callback=temp_get)

# 启动Web服务器
start_web_server()